package com.kkd.kkdapp.view;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

/**********************************
 *下拉刷新功能的基本类
 *将需要下来的界面添加到child中即可
 **/
public class ScrollerLayout extends LinearLayout {

	private static final int MIN_Y = 10;

	private int minY;

	/**
	 * 空闲状态
	 */
	public static final byte STATUS_IDLE = 0;

	/**
	 * 下拉：不满足hold条件
	 */
	public static final byte STATUS_PULL_DOWN = 1;

	/**
	 * 上拉：不满足hold条件
	 */
	public static final byte STATUS_PULL_UP = 2;
	/**
	 * 上拉后等待状态
	 */
	public static final byte STATUS_UP_HOLD = 3;

	/**
	 * 下拉后等待状态
	 */
	public static final byte STATUS_DOWN_HOLD = 4;

	/*
	 * 回弹动画状态
	 */
	public static final byte STATUS_ANIMATING = 5;

	/**
	 * 下拉：满足hold条件，松开将hold
	 * */
	public static final byte STATUS_PULL_DOWN_ENABLE = 6;

	/**
	 * 上拉：满足hold条件，松开将hold
	 * */
	public static final byte STATUS_PULL_UP_ENABLE = 7;

	private int mInitY;

	/**
	 * 当前状态
	 */
	protected byte mCurrentStatus = STATUS_IDLE;

	private View mTopView;

//	private View mCenterView;

	private View mBottomView;

	private float mTop;

	// /**
	// * 最初的滚动位置.第一次布局时滚动header的高度的距离
	// */
	// protected int mInitScrollY = 0;
	/**
	 * 最后一次触摸事件的y轴坐标
	 */
	protected float mLastY = 0;
	protected float mLastX = 0;

	private float mDownY = 0;

	// 手指滑动距离与下拉头的滑动距离比，中间会随正切函数变化
	private float radio = 2;

	/**
	 * 下拉刷新监听器
	 */
	protected OnRefreshListener mOnRefreshListener;
	/**
	 * 加载更多回调
	 */
	protected OnLoadListener mLoadListener;

	private ScrollStateProvider mProvider;

	private OnPullListener mPullListener;

	private LinearLayout mTopContioner;

	private LinearLayout mBottomContioner;

	public ScrollerLayout(Context context) {
		super(context);
		final float scale = context.getResources().getDisplayMetrics().density;
		minY = (int) (MIN_Y * scale + 0.5f);
	}
	
	public ScrollerLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		final float scale = context.getResources().getDisplayMetrics().density;
		minY = (int) (MIN_Y * scale + 0.5f);
		// if(mTopContioner == null){
		// mTopContioner = new LinearLayout(getContext());
		// mTopContioner.setLayoutParams(new
		// LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		// mTopContioner.setGravity(Gravity.BOTTOM|Gravity.CENTER);
		// addView(mTopContioner, 0);
		// }
		// if(mBottomContioner == null){
		// mBottomContioner = new LinearLayout(getContext());
		// mBottomContioner.setLayoutParams(new
		// LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		// mBottomContioner.setGravity(Gravity.TOP|Gravity.CENTER);
		// addView(mBottomContioner,getChildCount()-1);
		// }
	}

	

	public void addTopView(View view) {
		if (mTopView != null) {
			removeView(mTopView);
		}
		LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		addView(view, 0,lp);
		mTopView = view;
	}

	public void addBottomView(View view) {
		if (mBottomView != null) {
			removeView(mBottomView);
		}
		LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		addView(view,lp);
		mBottomView = view;
	}
	
	public boolean removeBottomView(){
		if (mBottomView != null) {
			removeView(mBottomView);
			return true;
		}
		return false;
	}
	
	public byte getCurrentState(){
		return mCurrentStatus;
	}
	
	public boolean removeTopView(){
		if (mTopView != null) {
			removeView(mTopView);
			return true;
		}
		return false;
	}

	// public void addCenterView(View view){
	// if(mCenterView != null){
	// removeView(mCenterView);
	// }
	// if(mTopView != null){
	// addView(view, 1);
	// }else{
	// addView(view);
	// }
	// mCenterView = view;
	// }

	/**
	 * 设置Content View的默认布局参数
	 */
//	protected void setDefaultContentLayoutParams() {
//		ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
//				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
//		mCenterView.setLayoutParams(params);
//	}

	public interface ScrollStateProvider {
		boolean canPullUp();

		boolean canPullDown();
	}

	public void setOnPullListener(OnPullListener listener) {
		mPullListener = listener;
	}
	
	public interface PullStateProvider{
		
		boolean canHoldUp(float top);
		
		boolean canHoldeDown(float top);
	}
	
	private PullStateProvider mPullStateProvider;
	
	public void setPullStateProvider(PullStateProvider provider){
		mPullStateProvider = provider;
	}

	public void setScrollStateProvider(ScrollStateProvider provider) {
		mProvider = provider;
	}

	public interface OnPullListener {
		void onPullUp(float pull);

		void onPullDown(float pull);

		void onPullStateChange(byte state);
	}

	private boolean isTop() {
		return mProvider == null ? false : mProvider.canPullDown();
	}

	private boolean isBottom() {
		return mProvider == null ? false : mProvider.canPullUp();
	}

	
	
	private boolean handleEvent;
	private int isPullDown = 0;//用来过滤左右滑动，0为初始状态，1表示为下拉

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		final int action = MotionEventCompat.getActionMasked(ev);
		if (mCurrentStatus == STATUS_ANIMATING) {
			return true;
		}
		switch (action) {

		case MotionEvent.ACTION_DOWN:
			mDownY = ev.getY();
			mLastY = mDownY;
			mLastX = ev.getX();
			handleEvent = true;
			isPullDown = 0;
			break;

		case MotionEvent.ACTION_MOVE:
			if (!handleEvent) {
				return true;
			}
			float dertaX = Math.abs(ev.getX()-mLastX);
			float dertaY = Math.abs(ev.getY()-mLastY);
			if(isPullDown==0&&dertaX<dertaY){
				isPullDown = 1;
			}
			if(isPullDown==1){

				
				int y = (int) ev.getY();
				switch (mCurrentStatus) {
				case STATUS_IDLE:
					if (Math.abs(y - mDownY) > minY
							&& ((y - mLastY < 0 && isBottom()) || (y - mLastY > 0 && isTop()))) {
						if (y - mLastY > 0) {
							changeState(STATUS_PULL_DOWN);
						} else {
							changeState(STATUS_PULL_UP);
						}
						handleMoveEvent(y);
						MotionEvent cancelEvent = MotionEvent.obtain(ev);
						cancelEvent
								.setAction(MotionEvent.ACTION_CANCEL
										| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
						super.dispatchTouchEvent(cancelEvent);
						return true;
					}
					break;
				case STATUS_UP_HOLD:
					MotionEvent cancelEvent = MotionEvent.obtain(ev);
					cancelEvent
							.setAction(MotionEvent.ACTION_CANCEL
									| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
					super.dispatchTouchEvent(cancelEvent);
				case STATUS_PULL_UP:
				case STATUS_PULL_UP_ENABLE:
					if ((int) mTop < 0) {
						handleMoveEvent(y);
						if ((mPullStateProvider!=null&&mPullStateProvider.canHoldeDown(mTop))||(mBottomView != null && mBottomView.getVisibility() == View.VISIBLE && mTop <= -mBottomView.getHeight())) {
							changeState(STATUS_PULL_UP_ENABLE);
						} else {
							changeState(STATUS_PULL_UP);
						}
					} else {
						changeState(STATUS_IDLE);
						MotionEvent downEvent = MotionEvent.obtain(ev);
						downEvent
								.setAction(MotionEvent.ACTION_DOWN
										| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
						super.dispatchTouchEvent(downEvent);
					}
					return true;
				case STATUS_DOWN_HOLD:
					MotionEvent cancelEvent1 = MotionEvent.obtain(ev);
					cancelEvent1
							.setAction(MotionEvent.ACTION_CANCEL
									| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
					super.dispatchTouchEvent(cancelEvent1);
				case STATUS_PULL_DOWN:
					if ((int) mTop > 0) {
						handleMoveEvent(y);
						if ((mPullStateProvider!=null&&mPullStateProvider.canHoldUp(mTop))||(mTopView != null && mTopView.getVisibility() == View.VISIBLE&& mTop >= mTopView.getHeight())) {
							changeState(STATUS_PULL_DOWN_ENABLE);
						} else {
							changeState(STATUS_PULL_DOWN);
						}
					} else {
						changeState(STATUS_IDLE);
						MotionEvent downEvent = MotionEvent.obtain(ev);
						downEvent
								.setAction(MotionEvent.ACTION_DOWN
										| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
						super.dispatchTouchEvent(downEvent);
					}
					return true;
				default:
					break;
				}
				mLastY = y;
			
			}
			
			break;

		case MotionEvent.ACTION_UP:
			handleEvent = false;
			switch (mCurrentStatus) {
			case STATUS_PULL_DOWN_ENABLE:
			case STATUS_PULL_UP_ENABLE:
				changeState(STATUS_ANIMATING);
				if (mTop != 0) {
					int end = 0;
					if (mTop > 0) {
						end = mTopView == null ? 0 : (mTopView.getHeight());
					} else {
						end = mBottomView == null ? 0 : (-mBottomView
								.getHeight());
					}
					ValueAnimator va = ValueAnimator.ofFloat(mTop, end);
					va.addUpdateListener(listener);
					va.addListener(alistener);
					va.setDuration((long) (Math.abs(end - mTop)));
					va.start();
				} else {

				}
				break;
			case STATUS_PULL_DOWN:
			case STATUS_PULL_UP:
			default:
				clearState();
				break;
			}
			break;
		}

		super.dispatchTouchEvent(ev);
		return true;
	}

	private void changeState(byte state) {
		if (mCurrentStatus != state) {
			mCurrentStatus = state;
			if (mPullListener != null)
				mPullListener.onPullStateChange(mCurrentStatus);
		}
	}

	private void handleMoveEvent(int y) {
		// 对实际滑动距离做缩小，造成用力拉的感觉
		mTop += (y - mLastY) / radio;
		// 根据下拉距离改变比例
		radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
				* Math.abs(mTop)));
		// //Log.w("WATCH_RADIO", radio+":top:"+mTop+":offset:"+mYOffset);
		if (mTop > 0) {
			if (mPullListener != null)
				mPullListener.onPullDown(mTop);
		} else {
			if (mPullListener != null)
				mPullListener.onPullUp(mTop);
		}
		// setY(mTop-mInitY);
		refreshView();
		// invalidate();
		// scrollBy(0, (int) (mTop-mInitY));
		mLastY = y;
	}

	private void refreshView() {
		scrollTo(0, -(int) (mTop - mInitY));
	}

	private ValueAnimator.AnimatorUpdateListener listener = new AnimatorUpdateListener() {

		@Override
		public void onAnimationUpdate(ValueAnimator animation) {
			float top = (Float) animation.getAnimatedValue();
			mTop = top;
			refreshView();
			if (mTop > 0) {
				if (mPullListener != null)
					mPullListener.onPullDown(mTop);
			} else {
				if (mPullListener != null)
					mPullListener.onPullUp(mTop);
			}
			// scrollTo(0, (int) (mTop-mInitY));
			// setY(mTop-mInitY);
			// postInvalidate();
		}
	};

	private Animator.AnimatorListener alistener = new AnimatorListener() {

		@Override
		public void onAnimationStart(Animator animation) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onAnimationRepeat(Animator animation) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onAnimationEnd(Animator animation) {
			post(new Runnable() {

				@Override
				public void run() {
					if (mTop == 0) {
						changeState(STATUS_IDLE);
					} else if (mTop > 0) {
						changeState(STATUS_DOWN_HOLD);
					} else if (mTop < 0) {
						changeState(STATUS_UP_HOLD);
					}
				}
			});
		}

		@Override
		public void onAnimationCancel(Animator animation) {
			// TODO Auto-generated method stub

		}
	};

	/*
	 * 丈量视图的宽、高。宽度为用户设置的宽度，高度则为header, content view, footer这三个子控件的高度只和。
	 * 
	 * @see android.view.View#onMeasure(int, int)
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = MeasureSpec.getSize(widthMeasureSpec);
		int childCount = getChildCount();
		int finalHeight = 0;
		for (int i = 0; i < childCount; i++) {
			View child = getChildAt(i);
			// measure
			measureChild(child, widthMeasureSpec, heightMeasureSpec);
			// 该view所需要的总高度
			if(child!=mTopView&&child!=mBottomView)
			finalHeight += child.getMeasuredHeight();
		}
		//Log.w("dsdsd", "" + finalHeight);
		setMeasuredDimension(width, finalHeight);
	}

	/*
	 * 布局函数，将header, content view,
	 * footer这三个view从上到下布局。布局完成后通过Scroller滚动到header的底部，即滚动距离为header的高度 +
	 * 本视图的paddingTop，从而达到隐藏header的效果.
	 * 
	 * @see android.view.ViewGroup#onLayout(boolean, int, int, int, int)
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// switch (getChildCount()) {
		// case 1:
		// mCenterView = getChildAt(0);
		// break;
		// case 2:
		// // mTopView = getChildAt(0);
		// mCenterView = getChildAt(0);
		// mBottomView = getChildAt(1);
		// break;
		// case 3:
		// mTopView = getChildAt(0);
		// mCenterView = getChildAt(1);
		// mBottomView = getChildAt(2);
		// break;
		// default:
		// break;
		// }
		int childCount = getChildCount();
		int top = getPaddingTop();
		for (int i = 0; i < childCount; i++) {
			View child = getChildAt(i);
			child.layout(l, top, r,
					child.getMeasuredHeight() + top);
			top += child.getMeasuredHeight();
		}

		// 计算初始化滑动的y轴距离
		int y = (mTopView == null ? getPaddingTop() : mTopView.getHeight()
				+ getPaddingTop());
		mInitY = y;
		// scrollTo(0, (int) (mTop-mInitY));
		//Log.w("gggg", "onLayout top" + getY() + ":::" + getTop());

		refreshView();
		// setY(mTop-mInitY);
		// 滑动到header view高度的位置, 从而达到隐藏header view的效果

		// mInitY =0;
	}

	public void clearState() {
		if (mTop != 0) {
			ValueAnimator va = ValueAnimator.ofFloat(mTop, 0);
			changeState(STATUS_ANIMATING);
			va.addUpdateListener(listener);
			va.addListener(alistener);
			va.setDuration((long) Math.abs(mTop));
			va.start();
		} else {

		}
	}

	// @Override
	// public void draw(Canvas canvas) {
	// canvas.translate(0, mTop-mInitY);
	// super.draw(canvas);
	// }

	public interface OnRefreshListener {
		void onRefresh();

	}

	public interface OnLoadListener {
		void onLoadMore();
	}

	public void ScrollToTop() {
		
		scrollTo(0, (int) (mTop - mInitY));
	}

}
